package com.googlecode.mylyn.ui.wizard;

import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.List;

import com.googlecode.mylyn.core.util.QueryUtils;
import com.googlecode.mylyn.core.util.RepositoryUtils;

/**
 * This wizard page allows the user to select either a predefined query or
 * indicate that he wants to create a custom one.
 */
public class GoogleCodeQuerySelectionPage extends AbstractRepositoryQueryPage {

    /**
     * Toggle button for creating a custom query.
     */
    private Button buttonCustom;

    /**
     * Toggle button for selecting a canned query.
     */
    private Button buttonCanned;

    /**
     * Viewer containing all the canned queries.
     */
    private ListViewer viewerQueries;

    private CannedQueryIdentifier selectedIdentifier;

    private CannedQueriesProvider cannedQueriesProvider;

    public GoogleCodeQuerySelectionPage(TaskRepository repository, IRepositoryQuery query) {
        super("New Google Code Query", repository, query);
        this.selectedIdentifier = getCannedIdentifier(query);
        this.cannedQueriesProvider = new CannedQueriesProvider(repository);
        setTitle("New Google Code Query"); //TODO translate
        setDescription("Please select a query type."); //TODO translate
        setPageComplete(false);
    }

    public void createControl(Composite parent) {
        IRepositoryQuery query = getQuery();
        boolean isCanQuery = QueryUtils.isCanQuery(query);

        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayoutData(new GridData());
        composite.setLayout(new GridLayout(2, false));
        buttonCustom = new Button(composite, SWT.RADIO);
        buttonCustom.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
        buttonCustom.setText("Create a new query &using a form"); //TODO translate
        buttonCustom.setSelection(!isCanQuery);

        buttonCanned = new Button(composite, SWT.RADIO);
        buttonCanned.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
        buttonCanned.setText("Use a &predefined query"); //TODO translate
        buttonCanned.setSelection(isCanQuery);
        buttonCanned.addSelectionListener(new CannedButtonListener());

        List identifiersList = new List(composite, SWT.V_SCROLL | SWT.BORDER);
        identifiersList.deselectAll();
        GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
        data.horizontalIndent = 15;
        identifiersList.setLayoutData(data);
        identifiersList.setEnabled(isCanQuery);

        viewerQueries = new ListViewer(identifiersList);
        viewerQueries.setContentProvider(cannedQueriesProvider);
        viewerQueries.setLabelProvider(new CannedQueryLabelProvider());
        viewerQueries.setInput(new Object());
        viewerQueries.addSelectionChangedListener(new CannedQuerySelectedListener());

        setControl(composite);
        restoreState(query);
    }

    private void restoreState(IRepositoryQuery query) {
        if (query != null) {
            String cannedParamter = query.getAttribute(QueryUtils.CAN);
            if (cannedParamter != null) {
                this.buttonCanned.setSelection(true);
                this.buttonCustom.setSelection(false);
                this.viewerQueries.getList().setEnabled(true);

                this.selectIdentifier(cannedParamter);
            }
        }
    }

    private void selectIdentifier(String parameterName) {
        selectCannedIdentifier(CannedQueryIdentifier.fromParameter(parameterName));
    }

    private void selectCannedIdentifier(CannedQueryIdentifier identifier) {
        if (identifier != null) {
            this.viewerQueries.setSelection(new StructuredSelection(identifier));
        } else {
            this.viewerQueries.setSelection(null);
        }
    }

    @Override
    public boolean canFlipToNextPage() {
        return this.buttonCustom.getSelection();
    }

    @Override
    public boolean isPageComplete() {
        if (buttonCustom.getSelection()) {
            return true;
        }
        IStructuredSelection selection = (IStructuredSelection) viewerQueries.getSelection();
        return selection.size() == 1 && super.isPageComplete();
    }

    @Override
    public void applyTo(IRepositoryQuery query) {
        String queryTitle = this.getQueryTitle();
        if (queryTitle != null) {
            query.setSummary(queryTitle);
        }

        //remove old attributes in case of editing
        query.getAttributes().clear();
        if (this.selectedIdentifier != null) {
            query.setAttribute(QueryUtils.CAN, this.selectedIdentifier.getParameter());
        }
    }

    @Override
    public String getQueryTitle() {
        if (this.selectedIdentifier != null) {
            return this.selectedIdentifier.getDescription();
        } else {
            return null;
        }
    }

    private static CannedQueryIdentifier getCannedIdentifier(IRepositoryQuery query) {
        return CannedQueryIdentifier.fromParameter(QueryUtils.CAN);
    }

    void cannedButtonSelected() {
        setErrorMessage(null);
        boolean isCannedSelected = buttonCanned.getSelection();
        this.viewerQueries.getList().setEnabled(isCannedSelected);
        getContainer().updateButtons();
    }

    void querySelected(SelectionChangedEvent event) {
        IStructuredSelection selection = (IStructuredSelection) event.getSelection();
        selectedIdentifier = (CannedQueryIdentifier) selection.getFirstElement();
        IWizardContainer container = getContainer();
        if (container != null && container.getCurrentPage() != null) {
            container.updateButtons();
        }
    }

    final class CannedButtonListener extends SelectionAdapter {

        @Override
        public void widgetSelected(SelectionEvent e) {
            GoogleCodeQuerySelectionPage.this.cannedButtonSelected();
        }
    }

    final class CannedQuerySelectedListener implements ISelectionChangedListener {

        public void selectionChanged(SelectionChangedEvent event) {
            GoogleCodeQuerySelectionPage.this.querySelected(event);
        }
    }

    final class CannedQueryLabelProvider extends LabelProvider {

        @Override
        public String getText(Object element) {
            if (element instanceof CannedQueryIdentifier) {
                return ((CannedQueryIdentifier) element).getDescription();
            } else {
                return super.getText(element);
            }
        }

    }

    final class CannedQueriesProvider implements IStructuredContentProvider {

        private TaskRepository repository;

        CannedQueriesProvider(TaskRepository repository) {
            this.repository = repository;
        }

        public CannedQueryIdentifier[] getElements(Object inputElement) {
            if (RepositoryUtils.isAnonymous(repository)) {
                return CannedQueryIdentifier.anonymousValues();
            }
            return CannedQueryIdentifier.values();
        }

        public void dispose() {
            // do nothing

        }

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            // do nothing
        }

    }

}
